﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using LumiSoft.Net.Mail;
using LumiSoft.Net.POP3.Client;
using LumiSoft.Net.POP3;

namespace 邮件访问内核
{
    public delegate void InstructionArrivedEventHandler(object sender, Mail_Message mail);
    public delegate void NewMailArrivedEventHandler(object sender, int count);
    
    /// <summary>
    /// 邮件访问内核
    /// </summary>
    public class MailBoxAccessShell
    {
        /// <summary>
        /// 收到新指令事件
        /// </summary>
        public event InstructionArrivedEventHandler InstructionArrived;
        /// <summary>
        /// 收到新邮件
        /// </summary>
        public event NewMailArrivedEventHandler NewMailArrived;
        /// <summary>
        /// 内核配置
        /// </summary>
        public MailBoxShellInfo shellInfo;
        /// <summary>
        /// POP3客户端
        /// </summary>
        public POP3_Client Client;
        /// <summary>
        /// 等待线程
        /// </summary>
        private Thread waitingThread;

        public MailBoxAccessShell(MailBoxShellInfo info)
        {
            shellInfo = info;
            Client = new POP3_Client();
        }

        /// <summary>
        /// 连接邮箱
        /// </summary>
        /// <returns></returns>
        public bool Connect()
        {
            try

            {
                Client.Connect(shellInfo.Host, shellInfo.Port);
                Client.Login(shellInfo.User, shellInfo.Password);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public void Close()
        {
            if (Client.IsConnected)
            {
                Client.Disconnect();
            }
        }

        /// <summary>
        /// 取出邮件
        /// </summary>
        /// <param name="count">最大数目</param>
        /// <returns></returns>
        public Mail_Message[] GetMails(int count)
        {
            List<Mail_Message> mails = new List<Mail_Message>(count);

            if (Connect())
            {
                for (int j = 0, i = Client.Messages.Count - 1; i >= 0 && j < count; i--, j++)
                {
                    Mail_Message mail = Mail_Message.ParseFromByte(Client.Messages[i].MessageToByte());
                    if (shellInfo.LastChekedTime < mail.Date)
                    {
                        mails.Add(mail);
                    }
                }
            }
            Close();
            return mails.ToArray();
        }

        /// <summary>
        /// 取出邮件
        /// </summary>
        /// <returns></returns>
        public Mail_Message[] GetMails()
        {
            string uid = string.Empty;
            DateTime time = shellInfo.LastChekedTime;
            List<Mail_Message> mails = new List<Mail_Message>();
            if (Connect())
            {
                for (int i = Client.Messages.Count - 1; i >= 0; i--)
                {
                    POP3_ClientMessage msg = Client.Messages[i];
                    if (uid == "")
                    {
                        uid = msg.UID;
                    }
                    if (shellInfo.LastUID == msg.UID)
                    {
                        break;
                    }
                    else
                    {
                        Mail_Message mail = Mail_Message.ParseFromByte(msg.MessageToByte());
                        if (mail.Date > time)
                        {
                            time = mail.Date;
                        }
                        if (mail.Date > shellInfo.LastChekedTime)
                        {
                            mails.Add(mail);
                            if (shellInfo.DeleteWhenFinished)
                            {
                                msg.MarkForDeletion();
                                uid = "";
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                shellInfo.LastUID = uid;
                shellInfo.LastChekedTime = time;
            }
            Close();
            return mails.ToArray();
        }

        /// <summary>
        /// 等待指令
        /// </summary>
        private void Waiting()
        {
            shellInfo.isWorking = true;
            do
            {
                if (ShellSleep())
                {
                    //收取邮件
                    Mail_Message[] mails = GetMails();
                    if (NewMailArrived != null)
                    {
                        NewMailArrived(this, mails.Length);
                    }

                    foreach (Mail_Message mail in mails)
                    {
                        //收到指令
                        if (mail.Subject == shellInfo.Feature)
                        {
                            if (shellInfo.Administrator != "")
                            {
                                string from = mail.From.ToString();
                                if (from.IndexOf(shellInfo.Administrator) == -1)
                                {
                                    continue;
                                }
                            }
                            if (InstructionArrived != null)
                            {
                                InstructionArrived(this, mail);
                            }
                        }
                    }
                }
                else
                {
                    break;
                }
            } while (shellInfo.isWorking);
        }

        /// <summary>
        /// 内核睡眠
        /// </summary>
        private bool ShellSleep()
        {
            for (int t = 0; t < shellInfo.Frequency; t++)
            {
                if (shellInfo.isWorking)
                {
                    if (shellInfo.RefreshNow)
                    {
                        shellInfo.RefreshNow = false;
                        return true;
                    }
                    Thread.Sleep(shellInfo.Delay);
                }
                else
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 异步等待
        /// </summary>
        public void AsynWaitingForInstruction()
        {
            Init();
            waitingThread = new Thread(new ThreadStart(Waiting));
            waitingThread.IsBackground = true;
            waitingThread.Start();
        }

        public void Init()
        {
            if (Connect())
            {
                if (Client.Messages.Count > 0)
                {
                    shellInfo.LastUID = Client.Messages[Client.Messages.Count - 1].UID;
                }
                else
                {
                    shellInfo.LastUID = "";
                }
                shellInfo.LastChekedTime = Client.ConnectTime;
                Close();
            }
        }
    }
}
